<script>
import { getLngLat } from '../js/AMapUtils.js';
import { AMapGeoCode } from '../js/AMapGeoCode.js';
import { debounce } from 'lodash-es';
import icon_marker from '../../../assets/mark_bs.png';

export default {
  name: 'AMapPositionPicker',
  emits: ['update:address', 'update:longitude', 'update:latitude', 'change'],
  props: {
    address: { type: [String], default: undefined },
    longitude: { type: [String, Number], default: undefined },
    latitude: { type: [String, Number], default: undefined },
    mapGetter: { type: Function, default: undefined },
    markerOptions: { type: [Object, Function], default: undefined },
    previewOnly: { type: Boolean, default: true },
    enableGeocode: { type: Boolean, default: false },
    geocodeImmediate: { type: Boolean, default: false },
    translate: { type: [String, Function], default: undefined },
  },
  created() {
    if (typeof this.mapGetter === 'function') {
      this.map = this.mapGetter();
    } else {
      throw new Error('mapGetter is not a function, please provide a function to return a map instance');
    }
    this.$watch(
      () => this.longitude + ',' + this.latitude,
      debounce((data) => {
        if (data !== this.position) {
          const lngLat = [this.longitude, this.latitude];
          this.addMarker(lngLat);
          if (this.enableGeocode && !this.address) {
            this.geoCode({ position: lngLat }).then(({ address }) => {
              this.$emit('update:address', address);
              this.$emit('change', {
                longitude: this.longitude,
                latitude: this.latitude,
                address: address,
              });
            });
          }
        }
      }, 500),
      { immediate: true }
    );
    this.$watch(
      () => this.address,
      debounce(() => {
        if (this.enableGeocode && this.address && !this.longitude && !this.latitude) {
          this.geoCode({ address: this.address }).then(({ position }) => {
            this.$emit('update:longitude', position.lng);
            this.$emit('update:latitude', position.lat);
            this.$emit('change', {
              longitude: position.lng,
              latitude: position.lat,
              address: this.address,
            });
          });
        }
      }, 500),
      { immediate: true }
    );
    this.$watch(
      () => this.previewOnly,
      () => {
        this.map[this.previewOnly === true ? 'off' : 'on']('click', this.onMapClick, this);
      },
      { immediate: true }
    );
  },
  unmounted() {
    this.destroy();
  },
  methods: {
    async onMapClick({ lnglat }) {
      this.position = lnglat.lng + ',' + lnglat.lat;
      this.addMarker(lnglat);
      // debugger;
      this.$emit('update:longitude', lnglat.lng);
      this.$emit('update:latitude', lnglat.lat);
      const address = await this.geoCode({ position: lnglat });
      this.$emit('update:address', address);
      this.$emit('change', {
        longitude: lnglat.lng,
        latitude: lnglat.lat,
        address: address,
      });
    },
    async geoCode({ position, address }) {
      if (!!this.previewOnly || !this.enableGeocode) {
        return {};
      }
      if (!this.aMapGeoCode) {
        this.aMapGeoCode = new AMapGeoCode();
      }
      position = getLngLat(position);
      if (position) {
        const address = await this.aMapGeoCode.regeocode(position);
        return { address };
      }
      if (address) {
        const position = await this.aMapGeoCode.geocode(address);
        return { position };
      }
      return {};
    },
    addMarker(position) {
      if (this.marker) {
        this.marker.setPosition(getLngLat(position));
        this.map.setFitView(this.marker);
        return;
      }
      const option = typeof this.markerOptions === 'function' ? this.markerOptions() : this.markerOptions;
      const opt = {
        content: `<img src="${icon_marker}" style="width: 38px;height: 64px"/>`,
        offset: new AMap.Pixel(-19, -64),
      };
      const marker = new AMap.Marker(
        Object.assign(opt, option, {
          position: getLngLat(position),
        })
      );
      this.marker = marker;
      this.map.add(this.marker);
      this.map.setFitView(this.marker);
    },
    destroy() {
      if (this.map) {
        if (this.marker) {
          this.map.remove(this.marker);
          this.marker = null;
        }
        this.map.off('click', this.onMapClick, this);
        this.map = null;
      }
    },
  },
  render() {
    return null;
  },
};
</script>
